package com.dxf.securitys.filter;

import com.dxf.common.exception.CommonEnum;
import com.dxf.common.utils.GlobalConstant;
import com.dxf.common.utils.RedisUtil;
import com.dxf.common.utils.ResponseUtil;
import com.dxf.common.utils.ResultJson;
import com.dxf.securitys.entity.SecurityUser;
import com.dxf.securitys.security.TokenManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.file.AccessDeniedException;
import java.util.Collection;

/**
 * 访问过滤器
 */
public class TokenAuthenticationFilter extends BasicAuthenticationFilter {
    private TokenManager tokenManager;
    private RedisUtil redisUtil;

    public TokenAuthenticationFilter(AuthenticationManager authManager, TokenManager tokenManager,
                                     RedisUtil redisUtil) {
        super(authManager);
        this.tokenManager = tokenManager;
        this.redisUtil = redisUtil;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        logger.info("=================" + req.getRequestURI());
        //不是admin路径放行
        if (req.getRequestURI().indexOf("admin") == -1) {
            logger.info("不是admin路径放行");
            chain.doFilter(req, res);
            return;
        }

        UsernamePasswordAuthenticationToken authentication = null;
        try {
                authentication = getAuthentication(req);

            if (authentication != null) {
                SecurityContextHolder.getContext().setAuthentication(authentication);
            } else {
                logger.error("authentication为空!");
                ResponseUtil.out(res, ResultJson.error(CommonEnum.STATUS_EXPIRED));
                return;
            }
        } catch (Exception e) {
            logger.error("更具token访问授权失败!");
            ResponseUtil.out(res, ResultJson.error(CommonEnum.STATUS_EXPIRED));
            return;
        }
        chain.doFilter(req, res);

    }

    /**
     * 4.更具token访问授权
     */
    private UsernamePasswordAuthenticationToken
    getAuthentication(HttpServletRequest request) {
        // token置于header里
        String token = request.getHeader(GlobalConstant.ACCESS_TOKEN);
        //token不为空且未过期
        if (!StringUtils.isEmpty(token) && !tokenManager.isTokenExpired(token)) {
            String userName = tokenManager.getUserFromToken(token);
            //正确解析username
            if (!StringUtils.isEmpty(userName)) {
                long expire = redisUtil.getExpire(userName);
                logger.info("================="+expire);
                //redis登陆状态未过期
                if (expire > 0) {
                    //更新登陆状态
                    if (expire <= GlobalConstant.REDIS_EXPIRE_TIME) {
                        logger.info("=========刷新redis在线状态=========");
                        redisUtil.expire(userName, GlobalConstant.REDIS_SAVE_TIME);
                    }
                    SecurityUser user = (SecurityUser) redisUtil.get(userName);
                    Collection<GrantedAuthority> authorities = user.getAuthorities();
                    logger.info("4.更具token访问授权==" + authorities);
                    return new UsernamePasswordAuthenticationToken(userName, null, authorities);
                }
                return null;
            }
            return null;
        }
        return null;
    }
}